home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2002 November / SGI Freeware 2002 November - Disc 2.iso / dist / fw_glimpse.idb / usr / freeware / src / glimpse-3.0 / index / glimpse.c.z / glimpse.c
C/C++ Source or Header  |  1997-09-09  |  30KB  |  921 lines

  1. /* Copyright (c) 1994 Sun Wu, Udi Manber, Burra Gopal.  All Rights Reserved. */
  2. /* ./glimpse/index/glimpse.c */
  3. #include "glimpse.h"
  4. #include <stdlib.h>
  5. #include <sys/time.h>
  6. #if    ISO_CHAR_SET
  7. #include <locale.h>    /* support for 8bit character set:ew@senate.be */
  8. #endif
  9.  
  10. extern char **environ;
  11. extern int errno;
  12. #if    BG_DEBUG
  13. extern FILE  *LOGFILE;     /* file descriptor for LOG output */
  14. #endif    /*BG_DEBUG*/
  15. extern FILE  *STATFILE;    /* file descriptor for statistical data about indexed files */
  16. extern FILE  *MESSAGEFILE;    /* file descriptor for important messages meant for the user */
  17. extern char  INDEX_DIR[MAX_LINE_LEN];
  18. extern struct stat istbuf;
  19.  
  20. extern int indexable_char[256];
  21. extern int GenerateHash;
  22. extern int KeepFilenames;
  23. extern int OneFilePerBlock;
  24. extern int IndexNumber;
  25. extern int CountWords;
  26. extern int StructuredIndex;
  27. extern int MAXWORDSPERFILE;
  28. extern int NUMERICWORDPERCENT;
  29. extern int AddToIndex;
  30. extern int DeleteFromIndex;
  31. extern int PurgeIndex;
  32. extern int FastIndex;
  33. extern int BuildDictionary;
  34. extern int BuildDictionaryExisting;
  35. extern int CompressAfterBuild;
  36. extern int IncludeHigherPriority;
  37. extern int FilenamesOnStdin;
  38. extern int UseFilters;
  39. extern int ByteLevelIndex;
  40. /* extern int IndexUnderscore; */
  41. extern int IndexableFile;
  42. extern int MAX_PER_MB, MAX_INDEX_PERCENT;
  43. extern int I_THRESHOLD;
  44. extern int BigHashTable;
  45. extern int IndexEverything;
  46. extern int BuildTurbo;
  47.  
  48. extern int AddedMaxWordsMessage;
  49. extern int AddedMixedWordsMessage;
  50.  
  51. extern int file_num;
  52. extern int old_file_num;
  53. extern int new_file_num;
  54. extern int file_id;
  55. extern int part_num;
  56. extern char **name_list[MAXNUM_INDIRECT];
  57. extern int p_table[MAX_PARTITION];
  58. extern int  *size_list[MAXNUM_INDIRECT];
  59. extern int p_size_list[];
  60. extern unsigned int *disable_list;
  61. extern int memory_usage;
  62. extern int mask_int[];
  63. extern int REAL_PARTITION, REAL_INDEX_BUF, MAX_ALL_INDEX, FILEMASK_SIZE;
  64. extern struct indices    *deletedlist;
  65. extern char sync_path[MAX_LINE_LEN];
  66.  
  67. extern set_usemalloc();    /* compress/misc.c */
  68.  
  69. char IProgname[MAX_LINE_LEN];
  70.  
  71. /*
  72.  * Has newnum crossed the boundary of an encoding? This is so rare that we
  73.  * needn't optimize it by changing the format of the old index and reusing it.
  74.  */
  75. cross_boundary(oldnum, newnum)
  76.     int    oldnum, newnum;
  77. {
  78.     int    ret;
  79.  
  80.     if (oldnum <= 0) return 0;
  81.     ret =  ( ((oldnum <= MaxNum8bPartition) && (newnum > MaxNum8bPartition)) ||
  82.          ((oldnum <= MaxNum12bPartition) && (newnum > MaxNum12bPartition)) ||
  83.          ((oldnum <= MaxNum16bPartition) && (newnum > MaxNum16bPartition)) );
  84.     if (ret) fprintf(MESSAGEFILE, "Must change index format. Commencing fresh indexing...\n");
  85.     return ret;
  86. }
  87.  
  88. determine_sync()
  89. {
  90.     char    S[1024], s1[256], s2[256];
  91.     FILE    *fp;
  92.     int    i, ret;
  93.  
  94.     strcpy(sync_path, "sync");
  95.     sprintf(S, "exec whereis sync > /tmp/zz.%d", getpid());
  96.     system(S);
  97.     sprintf(S, "/tmp/zz.%d", getpid());
  98.     if ((fp = fopen(S, "r")) == NULL) {
  99.         /* printf("11111\n"); */
  100.         return 0;
  101.     }
  102.     if ((ret = fread(S, 1, 1024, fp)) <= 0) {
  103.         sprintf(S, "/tmp/zz.%d", getpid());
  104.         unlink(S);
  105.         fclose(fp);
  106.         /* printf("22222\n"); */
  107.         return 0;
  108.     }
  109.     sprintf(s1, "/tmp/zz.%d", getpid());
  110.     unlink(s1);
  111.     fclose(fp);
  112.     /* printf("read: %s\n", S); */
  113.  
  114.     sscanf(S, "%s%s", s1, s2);
  115.     /* printf("s1=%s s2=%s\n", s1, s2); */
  116.     if (strncmp(s1, "sync", 4)) {
  117.         /* printf("33333\n"); */
  118.         return 0;
  119.     }
  120.     if (!strcmp(s2, "") || !strcmp(s2, " ")) {
  121.         /* printf("44444\n"); */
  122.         return 0;
  123.     }
  124.     if (strstr(s2, "sync") == NULL) {
  125.         /* printf("55555\n"); */
  126.         return 0;
  127.     }
  128.     strcpy(sync_path, s2);
  129.     /* printf("Using sync in: %s\n", sync_path); */
  130.     return 1;
  131. }
  132.  
  133. main(argc, argv)
  134. int argc;
  135. char **argv;
  136. {
  137.     int pid = getpid();
  138.     int    i, m = 0;
  139.     char *indexdir;
  140.     char s[MAX_LINE_LEN], s1[MAX_LINE_LEN];
  141.     char working_dir[MAX_LINE_LEN];
  142.     FILE *tmpfp;
  143.     char hash_file[MAX_LINE_LEN], string_file[MAX_LINE_LEN], freq_file[MAX_LINE_LEN];
  144.     char tmpbuf[1024];
  145.     struct stat stbuf;
  146.     char name[MAX_LINE_LEN];
  147.     char outname[MAX_LINE_LEN];
  148.     int specialwords, threshold;
  149.     int backup;
  150.     struct indices *get_removed_indices();
  151.     struct timeval tv;
  152.  
  153. #if    ISO_CHAR_SET
  154.     setlocale(LC_ALL,""); /* support for 8bit character set: ew@senate.be, Henrik.Martin@eua.ericsson.se */
  155. #endif
  156.     BuildDictionary = ON;
  157.     set_usemalloc();
  158.     srand(pid);
  159.     umask(077);
  160.     determine_sync();
  161.  
  162.     INDEX_DIR[0] = '\0';
  163.     specialwords = threshold = -1;    /* so that compute_dictionary can use defaults not visible here */
  164.     strncpy(IProgname, argv[0], MAX_LINE_LEN);
  165.     memset(size_list, '\0', sizeof(int *) * MAXNUM_INDIRECT);    /* free it once partition successfully calculates p_size_list */
  166.     memset(name_list, '\0', sizeof(char **) * MAXNUM_INDIRECT);
  167.     memset(p_size_list, '\0', sizeof(int) * MAX_PARTITION);
  168.     build_filename_hashtable((char *)NULL, 0);
  169.  
  170.     /*
  171.      * Process options.
  172.      */
  173.  
  174.     while (argc > 1) {
  175.     if (strcmp(argv[1], "-help") == 0) {
  176.         return usage(1);
  177.     }
  178. #if    !BUILDCAST
  179.     else if (strcmp(argv[1], "-V") == 0) {
  180.         printf("\nThis is glimpseindex version %s, %s.\n\n", GLIMPSE_VERSION, GLIMPSE_DATE);
  181.         return(0);
  182.     }
  183.     else if (strcmp(argv[1], "-T") == 0) {
  184.         BuildTurbo = ON;
  185.         argc --; argv ++;
  186.     }
  187.     else if (strcmp(argv[1], "-I") == 0) {
  188.         IndexableFile = ON;
  189.         argc --; argv ++;
  190.     }
  191.     else if(strcmp(argv[1], "-a") == 0) {
  192.         AddToIndex = ON;
  193.         argc--; argv++;
  194.     }
  195.     else if(strcmp(argv[1], "-b") == 0) {
  196.         ByteLevelIndex = ON;
  197.         argc--; argv++;
  198.     }
  199.     else if(strcmp(argv[1], "-c") == 0) {
  200.         CountWords = ON;
  201.         argc--; argv++;
  202.     }
  203.     else if(strcmp(argv[1], "-d") == 0) {
  204.         DeleteFromIndex = ON;
  205.         argc --; argv ++;
  206.     }
  207.     else if(strcmp(argv[1], "-D") == 0) {
  208.         PurgeIndex = OFF;
  209.         argc --; argv ++;
  210.     }
  211.     else if(strcmp(argv[1], "-f") == 0) {
  212.         FastIndex = ON;
  213.         argc--; argv++;
  214.     }
  215.     else if (strcmp(argv[1], "-o") == 0) {
  216.         OneFilePerBlock = ON;
  217.         argc --; argv ++;
  218.     }
  219.     else if (strcmp(argv[1], "-s") == 0) {
  220.         StructuredIndex = ON;
  221.         argc --; argv ++;
  222.     }
  223.     else if(strcmp(argv[1], "-z") == 0) {
  224.         UseFilters = ON;
  225.         argc--; argv++;
  226.     }
  227. #else    /*!BUILDCAST*/
  228.     else if (strcmp(argv[1], "-V") == 0) {
  229.         printf("\nThis is buildcast version %s, %s.\n\n", GLIMPSE_VERSION, GLIMPSE_DATE);
  230.         return(0);
  231.     }
  232.     else if(strcmp(argv[1], "-C") == 0) {
  233.         CompressAfterBuild = ON;
  234.         argc --; argv ++;
  235.     }
  236.     else if(strcmp(argv[1], "-E") == 0) {
  237.         BuildDictionaryExisting = ON;
  238.         argc --; argv ++;
  239.     }
  240.     else if (strcmp(argv[1], "-t") == 0) {
  241.         if ((argc <= 2) || !(isdigit(argv[2][0]))) {
  242.         return usage(1);
  243.         }
  244.         else {
  245.         threshold = atoi(argv[2]);
  246.         argc -= 2; argv += 2;
  247.         }
  248.     }
  249.     else if (strcmp(argv[1], "-l") == 0) {
  250.         if ((argc <= 2) || !(isdigit(argv[2][0]))) {
  251.         return usage(1);
  252.         }
  253.         else {
  254.         specialwords = atoi(argv[2]);
  255.         argc -= 2; argv += 2;
  256.         }
  257.     }
  258. #endif    /*!BUILDCAST*/
  259.     else if (strcmp(argv[1], "-M") == 0) {
  260.         if (argc == 2) {
  261.         fprintf(stderr, "-M should be followed by the amount of memory in MB for indexing words\n");
  262.         return usage(1);
  263.         }
  264.         m = atoi(argv[2]);
  265.         if (m < 1) {
  266.         fprintf(stderr, "Ignoring -M %d (< 1 MB). Using default value of about 2 MB\n", m);
  267.         return usage(1);
  268.         }
  269.         else {
  270.         /*
  271.          * Calculate I_THRESHOLD approximately. Note: 2*1024*1024*2 / (2*24 + 32 + 12) = 47662, DEF_I_THRESHOLD = 40000, so OK
  272.          * N * sizeofindices + N*(avgwordlen + sizeoftoken)/indicespertoken <= mem
  273.          * elemsperset = occurrences/indicespertoken
  274.          * N <= mem * occurrences / (sizeofindices*indicespertoken + avgwordlen + sizeoftoken)
  275.          */
  276.         I_THRESHOLD = m * 1024 * 1024 * (INDICES_PER_TOKEN) /
  277.                 (INDICES_PER_TOKEN * sizeof(struct indices) + sizeof(struct token) + AVG_WORD_LEN);
  278.         fprintf(stderr, "Using %d words as threshold before merge\n", I_THRESHOLD/INDICES_PER_TOKEN);
  279.         }
  280.         argc -= 2; argv += 2;
  281.     }
  282.     else if (strcmp(argv[1], "-w") == 0) {
  283.         if (argc == 2) {
  284.         fprintf(stderr, "-w should be followed by the number of words\n");
  285.         return usage(1);
  286.         }
  287.         MAXWORDSPERFILE = atoi(argv[2]);
  288.         argc -= 2; argv += 2;
  289.     }
  290.     else if (strcmp(argv[1], "-S") == 0) {
  291.         if (argc == 2) {
  292.         fprintf(stderr, "-S should be followed by the stop list limit\n");
  293.         return usage(1);
  294.         }
  295.         MAX_PER_MB = MAX_INDEX_PERCENT = atoi(argv[2]);
  296.         argc -= 2; argv += 2;
  297.     }
  298.     else if(strcmp(argv[1], "-n") == 0) {
  299.         IndexNumber = ON;
  300.         if ((argc <= 2) || !(isdigit(argv[2][0]))) {    /* -n has no arg */
  301.         argc --; argv ++;
  302.         }
  303.         else {
  304.         NUMERICWORDPERCENT = atoi(argv[2]);
  305.         if ((NUMERICWORDPERCENT > 100) || (NUMERICWORDPERCENT < 0)) {
  306.             fprintf(stderr, "The percentage of numeric words must be in [0..100]\n");
  307.             return usage(1);
  308.         }
  309.         argc-=2; argv+=2;
  310.         }
  311.     }
  312.     else if(strcmp(argv[1], "-h") == 0) {
  313.         /* I want to generate .glimpse_filehash and .glimpse_filehash_index */
  314.         GenerateHash = ON;
  315.         argc --; argv ++;
  316.     }
  317.     else if(strcmp(argv[1], "-i") == 0) {
  318.         IncludeHigherPriority = ON;
  319.         argc --; argv ++;
  320.     }
  321.     else if(strcmp(argv[1], "-k") == 0) {
  322.         /* I want to know what files were there before: used in SFS to compute new sets from old ones */
  323.         KeepFilenames = ON;
  324.         argc --; argv ++;
  325.     }
  326.     else if (strcmp(argv[1], "-B") == 0) {
  327.         BigHashTable = 1;
  328.         argc --; argv ++;
  329.     }
  330.     else if (strcmp(argv[1], "-E") == 0) {
  331.         IndexEverything = 1;    /* without doing stat tests, etc. */
  332.         argc --; argv ++;
  333.     }
  334.     else if(strcmp(argv[1], "-F") == 0) {
  335.         FilenamesOnStdin = ON;
  336.         argc--; argv++;
  337.     }
  338.     /*
  339.     else if(strcmp(argv[1], "-u") == 0) {
  340.         IndexUnderscore = ON;
  341.         argc--; argv++;
  342.     }
  343.     */
  344.     else if (strcmp(argv[1], "-H") == 0) {
  345.         if (argc == 2) {
  346.         fprintf(stderr, "-H should be followed by a directory name\n");
  347.         return usage(1);
  348.         }
  349.         strncpy(INDEX_DIR, argv[2], MAX_LINE_LEN);
  350.         argc -= 2; argv += 2;
  351.     }
  352.     else break;    /* rest are directory names */
  353.     }
  354.  
  355.     BuildTurbo = ON;    /* always ON: user can remove .glimpse_turbo if not needed */
  356.     /*
  357.      * Look for invalid option combos.
  358.      */
  359.  
  360.     if ((argc<=1) && (!FilenamesOnStdin) && !FastIndex) {
  361.     return usage(1);
  362.     }
  363.  
  364.     if (DeleteFromIndex && (AddToIndex || CountWords || IndexableFile)) {
  365.     /* With -f, it is automatic for files not found in OS but present in index; without it, an explicit set of files is required as argument on cmdline */
  366.     fprintf(stderr, "-d cannot be used with -I, -a or -c (see man pages)\n");
  367.     exit(2);
  368.     }
  369.  
  370.     if (ByteLevelIndex) {
  371.     if (MAX_PER_MB <= 0) {
  372.         fprintf(stderr, "Stop list limit (#of occurrences per MB) '%d' must be > 0\n", MAX_PER_MB);
  373.         exit(2);
  374.     }
  375.     }
  376.     else if (OneFilePerBlock) {
  377.     if ((MAX_INDEX_PERCENT <= 0) || (MAX_INDEX_PERCENT > 100)) {
  378.         fprintf(stderr, "Stop list limit (%% of occurrences in files) '%d' must be in (0, 100]\n", MAX_INDEX_PERCENT);
  379.         exit(2);
  380.     }
  381.     }
  382.  
  383.     /*
  384.      * Find the index directory since it is used in all options.
  385.      */
  386.  
  387.     if (INDEX_DIR[0] == '\0') {
  388.     if ((indexdir = getenv("HOME")) == NULL) {
  389.         getcwd(INDEX_DIR, MAX_LINE_LEN-1);
  390.         fprintf(stderr, "Using working-directory '%s' to store index\n\n", INDEX_DIR);
  391.     }
  392.     else strncpy(INDEX_DIR, indexdir, MAX_LINE_LEN);
  393.     }
  394.     getcwd(working_dir, MAX_LINE_LEN - 1);
  395.     if (-1 == chdir(INDEX_DIR)) {
  396.     fprintf(stderr, "Cannot change directory to %s\n", INDEX_DIR);
  397.     return usage(0);
  398.     }
  399.     getcwd(INDEX_DIR, MAX_LINE_LEN - 1);    /* must be absolute path name */
  400.     chdir(working_dir);    /* get back to where you were */
  401.  
  402.     if (IndexableFile) {    /* traverse the given directories and output names of files that are indexable on stdout */
  403.     partition(argc, argv);
  404.     return 0;
  405.     }
  406.     else {
  407. #if    BUILDCAST
  408.     printf("\nThis is buildcast version %s, %s.\n\n", GLIMPSE_VERSION, GLIMPSE_DATE);
  409. #else    /*BUILDCAST*/
  410.     printf("\nThis is glimpseindex version %s, %s.\n\n", GLIMPSE_VERSION, GLIMPSE_DATE);
  411. #endif    /*BUILDCAST*/
  412.     }
  413.  
  414.     if (ByteLevelIndex) {
  415. #if    0
  416.     /* We'll worry about these things later */
  417.     if (AddToIndex || DeleteFromIndex || FastIndex) {
  418.         fprintf(stderr, "Fresh indexing recommended: -a, -d and -f are not supported with -b as yet\n");
  419.         exit(1);
  420.     }
  421.     AddToIndex = FastIndex = OFF;
  422. #endif
  423.     CountWords = OFF;
  424.     OneFilePerBlock = ON;
  425.     }
  426.  
  427.     /*
  428.      * CONVENTION: all the relevant output is on stdout; warnings/errors are on stderr.
  429.      * Initialize / open important files.
  430.      */
  431.  
  432.     read_filters(INDEX_DIR, UseFilters);
  433.  
  434.     freq_file[0] = hash_file[0] = string_file[0] = '\0';
  435.     strcpy(freq_file, INDEX_DIR);
  436.     strcat(freq_file, "/");
  437.     strcat(freq_file, DEF_FREQ_FILE);
  438.     strcpy(hash_file, INDEX_DIR);
  439.     strcat(hash_file, "/");
  440.     strcat(hash_file, DEF_HASH_FILE);
  441.     strcpy(string_file, INDEX_DIR);
  442.     strcat(string_file, "/");
  443.     strcat(string_file, DEF_STRING_FILE);
  444.     initialize_tuncompress(string_file, freq_file, 0);
  445.  
  446. #if    BG_DEBUG
  447.     sprintf(s, "%s/%s", INDEX_DIR, DEF_LOG_FILE);
  448.     if((LOGFILE = fopen(s, "w")) == 0) {
  449.     fprintf(stderr, "can't open %s for writing\n", s);
  450.     LOGFILE = stderr;
  451.     }
  452. #endif    /*BG_DEBUG*/
  453.  
  454.     sprintf(s, "%s/%s", INDEX_DIR, DEF_MESSAGE_FILE);
  455.     if((MESSAGEFILE = fopen(s, "w")) == 0) {
  456.     fprintf(stderr, "can't open %s for writing\n", s);
  457.     MESSAGEFILE = stderr;
  458.     }
  459.  
  460.     sprintf(s, "%s/%s", INDEX_DIR, DEF_STAT_FILE);
  461.     if((STATFILE = fopen(s, "a")) == 0) {
  462.     fprintf(stderr, "can't open %s for appending\n", s);
  463.     STATFILE = stderr;
  464.     }
  465.     gettimeofday(&tv, NULL);
  466. #if    BUILDCAST
  467.     fprintf(STATFILE, "\nThis is buildcast version %s, %s. %s", GLIMPSE_VERSION, GLIMPSE_DATE, ctime(&tv.tv_sec));
  468. #else
  469.     fprintf(STATFILE, "\nThis is glimpseindex version %s, %s. %s", GLIMPSE_VERSION, GLIMPSE_DATE, ctime(&tv.tv_sec));
  470. #endif
  471.  
  472. #if    BG_DEBUG
  473.     fprintf(LOGFILE, "Index Directory = %s\n\n", INDEX_DIR);
  474. #endif    /*BG_DEBUG*/
  475.     if (MAXWORDSPERFILE != 0) fprintf(MESSAGEFILE, "Index: maximum number of indexed words per file = %d\n", MAXWORDSPERFILE);
  476.     else fprintf(MESSAGEFILE, "Index: maximum number of indexed words per file = infinity\n");
  477.     fprintf(MESSAGEFILE, "Index: maximum percentage of numeric words per file = %d\n", NUMERICWORDPERCENT);
  478.  
  479.     set_indexable_char(indexable_char);
  480.  
  481. #if    BUILDCAST
  482.  
  483.     CountWords = ON;
  484.     AddToIndex = OFF;
  485.     FastIndex = OFF;
  486.  
  487.     /* Save old search-dictionaries */
  488.  
  489.     sprintf(s, "%s/.glimpse_index", INDEX_DIR);
  490.     if (!access(s, R_OK)) {
  491.     sprintf(s, "%s/.glimpse_tempdir.%d", INDEX_DIR, pid);
  492.     if (-1 == mkdir(s, 0700)) {
  493.         fprintf(stderr, "cannot create temporary directory %s\n", s);
  494.         return -1;
  495.     }
  496. #if    SFS_COMPAT
  497.     sprintf(s, "%s/%s", INDEX_DIR, INDEX_FILE);
  498.     sprintf(s1, "%s/.glimpse_tempdir.%d", INDEX_DIR, pid);
  499.     rename(s, s1);
  500. #else
  501.     sprintf(s, "exec %s -f %s/%s %s/.glimpse_tempdir.%d\n", SYSTEM_MV, INDEX_DIR, INDEX_FILE, INDEX_DIR, pid);
  502.     system(s);
  503. #endif
  504. #if    SFS_COMPAT
  505.     sprintf(s, "%s/%s", INDEX_DIR, P_TABLE);
  506.     sprintf(s1, "%s/.glimpse_tempdir.%d", INDEX_DIR, pid);
  507.     rename(s, s1);
  508. #else
  509.     sprintf(s, "exec %s -f %s/%s %s/.glimpse_tempdir.%d\n", SYSTEM_MV, INDEX_DIR, P_TABLE, INDEX_DIR, pid);
  510.     system(s);
  511. #endif
  512. #if    SFS_COMPAT
  513.     sprintf(s, "%s/%s", INDEX_DIR, NAME_LIST);
  514.     sprintf(s1, "%s/.glimpse_tempdir.%d", INDEX_DIR, pid);
  515.     rename(s, s1);
  516. #else
  517.     sprintf(s, "exec %s -f %s/%s %s/.glimpse_tempdir.%d\n", SYSTEM_MV, INDEX_DIR, NAME_LIST, INDEX_DIR, pid);
  518.     system(s);
  519. #endif
  520. #if    SFS_COMPAT
  521.     sprintf(s, "%s/%s", INDEX_DIR, NAME_LIST_INDEX);
  522.     sprintf(s1, "%s/.glimpse_tempdir.%d", INDEX_DIR, pid);
  523.     rename(s, s1);
  524. #else
  525.     sprintf(s, "exec %s -f %s/%s %s/.glimpse_tempdir.%d\n", SYSTEM_MV, INDEX_DIR, NAME_LIST_INDEX, INDEX_DIR, pid);
  526.     system(s);
  527. #endif
  528. #if    SFS_COMPAT
  529.     sprintf(s, "%s/%s", INDEX_DIR, NAME_HASH);
  530.     sprintf(s1, "%s/.glimpse_tempdir.%d", INDEX_DIR, pid);
  531.     rename(s, s1);
  532. #else
  533.     sprintf(s, "exec %s -f %s/%s %s/.glimpse_tempdir.%d\n", SYSTEM_MV, INDEX_DIR, NAME_HASH, INDEX_DIR, pid);
  534.     system(s);
  535. #endif
  536. #if    SFS_COMPAT
  537.     sprintf(s, "%s/%s", INDEX_DIR, NAME_HASH_INDEX);
  538.     sprintf(s1, "%s/.glimpse_tempdir.%d", INDEX_DIR, pid);
  539.     rename(s, s1);
  540. #else
  541.     sprintf(s, "exec %s -f %s/%s %s/.glimpse_tempdir.%d\n", SYSTEM_MV, INDEX_DIR, NAME_HASH_INDEX, INDEX_DIR, pid);
  542.     system(s);
  543. #endif
  544. #if    SFS_COMPAT
  545.     sprintf(s, "%s/%s", INDEX_DIR, MINI_FILE);
  546.     sprintf(s1, "%s/.glimpse_tempdir.%d", INDEX_DIR, pid);
  547.     rename(s, s1);
  548. #else
  549.     sprintf(s, "exec %s -f %s/%s %s/.glimpse_tempdir.%d\n", SYSTEM_MV, INDEX_DIR, MINI_FILE, INDEX_DIR, pid);
  550.     system(s);
  551. #endif
  552. #if    SFS_COMPAT
  553.     sprintf(s, "%s/%s", INDEX_DIR, DEF_STAT_FILE);
  554.     sprintf(s1, "%s/.glimpse_tempdir.%d", INDEX_DIR, pid);
  555.     rename(s, s1);
  556. #else
  557.     sprintf(s, "exec %s -f %s/%s %s/.glimpse_tempdir.%d\n", SYSTEM_MV, INDEX_DIR, DEF_STAT_FILE, INDEX_DIR, pid);
  558.     system(s);
  559. #endif
  560.     /* Don't save messages, log, debug, etc. */
  561.     sprintf(s, "%s/.glimpse_attributes", INDEX_DIR);
  562.     if (!access(s, R_OK)) {
  563. #if    SFS_COMPAT
  564.         sprintf(s, "%s/%s", INDEX_DIR, ATTRIBUTE_FILE);
  565.         sprintf(s1, "%s/.glimpse_tempdir.%d", INDEX_DIR, pid);
  566.         rename(s, s1);
  567. #else
  568.         sprintf(s, "exec %s -f %s/%s %s/.glimpse_tempdir.%d\n", SYSTEM_MV, INDEX_DIR, ATTRIBUTE_FILE, INDEX_DIR, pid);
  569.         system(s);
  570. #endif
  571.     }
  572.     }
  573.  
  574.     /* Backup old cast-dictionaries: don't use move since indexing might want to use them */
  575.     sprintf(s, "%s/.glimpse_quick", INDEX_DIR);
  576.     if (!access(s, R_OK)) {    /* there are previous cast dictionaries */
  577.     backup = rand();
  578.     sprintf(s, "%s/.glimpse_backup.%x", INDEX_DIR, backup);
  579.     if (-1 == mkdir(s, 0700)) {
  580.         fprintf(stderr, "cannot create backup directory %s\n", s);
  581.         return -1;
  582.     }
  583.     sprintf(s, "exec %s -f %s/.glimpse_quick %s/.glimpse_backup.%x\n", SYSTEM_CP, INDEX_DIR, INDEX_DIR, backup);
  584.     system(s);
  585.     sprintf(s, "exec %s -f %s/.glimpse_compress %s/.glimpse_backup.%x\n", SYSTEM_CP, INDEX_DIR, INDEX_DIR, backup);
  586.     system(s);
  587.     sprintf(s, "exec %s -f %s/.glimpse_compress.index %s/.glimpse_backup.%x\n", SYSTEM_CP, INDEX_DIR, INDEX_DIR, backup);
  588.     system(s);
  589.     sprintf(s, "exec %s -f %s/.glimpse_uncompress %s/.glimpse_backup.%x\n", SYSTEM_CP, INDEX_DIR, INDEX_DIR, backup);
  590.     system(s);
  591.     sprintf(s, "exec %s -f %s/.glimpse_uncompress.index %s/.glimpse_backup.%x\n", SYSTEM_CP, INDEX_DIR, INDEX_DIR, backup);
  592.     system(s);
  593.     printf("Saved previous cast-dictionary in %s/.glimpse_backup.%x\n", INDEX_DIR, backup);
  594.     }
  595.  
  596.     /* Now index these files, and build new dictionaries */
  597.     partition(argc, argv);
  598.     initialize_data_structures(file_num);
  599.     old_file_num = file_num;
  600.     build_index();
  601.  
  602.     cleanup();
  603.     save_data_structures();
  604.     destroy_filename_hashtable();
  605.     uninitialize_common();
  606.     uninitialize_tcompress();
  607.     uninitialize_tuncompress();
  608.     compute_dictionary(threshold, DISKBLOCKSIZE, specialwords, INDEX_DIR);
  609.  
  610.     if (CompressAfterBuild) {
  611.     /* For the new compression */
  612.     if (!initialize_tcompress(hash_file, freq_file, TC_ERRORMSGS)) goto docleanup;
  613.     printf("Compressing files with new dictionary...\n");
  614.     /* Use the set of file-names collected during partition() / modified during build_hash */
  615.     for(i=0; i<file_num; i++) {
  616.         if ((disable_list != NULL) && (disable_list[block2index(i)] & mask_int[i%(8*sizeof(int))])) continue;    /* nop since disable_list IS NULL */
  617.         strcpy(name, LIST_GET(name_list, i));
  618.         tcompress_file(name, outname, TC_REMOVE | TC_EASYSEARCH | TC_OVERWRITE | TC_NOPROMPT);
  619.     }
  620.     }
  621.  
  622. docleanup:
  623.     /* Restore old search-dictionaries */
  624.     sprintf(s, "%s/.glimpse_tempdir.%d/.glimpse_index", INDEX_DIR, pid);
  625.     if (!access(s, R_OK)) {
  626. #if    SFS_COMPAT
  627.     sprintf(s1, "%s/%s", INDEX_DIR, INDEX_FILE);
  628.     sprintf(s, "%s/.glimpse_tempdir.%d/%s", INDEX_DIR, pid, INDEX_FILE);
  629.     rename(s, s1);
  630.     sprintf(s1, "%s/%s", INDEX_DIR, P_TABLE);
  631.     sprintf(s, "%s/.glimpse_tempdir.%d/%s", INDEX_DIR, pid, P_TABLE);
  632.     rename(s, s1);
  633.     sprintf(s1, "%s/%s", INDEX_DIR, NAME_LIST);
  634.     sprintf(s, "%s/.glimpse_tempdir.%d/%s", INDEX_DIR, pid, NAME_LIST);
  635.     rename(s, s1);
  636.     sprintf(s1, "%s/%s", INDEX_DIR, NAME_LIST_INDEX);
  637.     sprintf(s, "%s/.glimpse_tempdir.%d/%s", INDEX_DIR, pid, NAME_LIST_INDEX);
  638.     rename(s, s1);
  639.     sprintf(s1, "%s/%s", INDEX_DIR, NAME_HASH);
  640.     sprintf(s, "%s/.glimpse_tempdir.%d/%s", INDEX_DIR, pid, NAME_HASH);
  641.     rename(s, s1);
  642.     sprintf(s1, "%s/%s", INDEX_DIR, NAME_HASH_INDEX);
  643.     sprintf(s, "%s/.glimpse_tempdir.%d/%s", INDEX_DIR, pid, NAME_HASH_INDEX);
  644.     rename(s, s1);
  645.     sprintf(s1, "%s/%s", INDEX_DIR, MINI_FILE);
  646.     sprintf(s, "%s/.glimpse_tempdir.%d/%s", INDEX_DIR, pid, MINI_FILE);
  647.     rename(s, s1);
  648.     sprintf(s1, "%s/%s", INDEX_DIR, DEF_STAT_FILE);
  649.     sprintf(s, "%s/.glimpse_tempdir.%d/%s", INDEX_DIR, pid, DEF_STAT_FILE);
  650.     rename(s, s1);
  651.     sprintf(s1, "%s/%s", INDEX_DIR, ATTRIBUTE_FILE);
  652.     sprintf(s, "%s/.glimpse_tempdir.%d/%s", INDEX_DIR, pid, ATTRIBUTE_FILE);
  653.     rename(s, s1);
  654. #else
  655.     sprintf(s, "exec %s -f %s/.glimpse_tempdir.%d/.glimpse_* %s\n", SYSTEM_MV, INDEX_DIR, pid, INDEX_DIR);
  656.     system(s);
  657. #endif
  658.     sprintf(s, "%s/.glimpse_tempdir.%d", INDEX_DIR, pid);
  659.     rmdir(s);
  660.     }
  661.     printf("\nBuilt new cast-dictionary in %s\n", INDEX_DIR);
  662.  
  663. #else    /*BUILDCAST*/
  664.  
  665.     if (AddToIndex || DeleteFromIndex || FastIndex) {
  666.     /* Not handling byte level indices here for now */
  667.     int    indextype;
  668.  
  669.     sprintf(s, "%s/%s", INDEX_DIR, INDEX_FILE);
  670.     if (-1 == stat(s, &istbuf)) {
  671.         if (AddToIndex || DeleteFromIndex) {
  672.         fprintf(stderr, "Cannot find previous index! Fresh indexing recommended\n", s);
  673.         return usage(0);
  674.         }
  675.         file_num = 0;
  676.         file_id = 0;
  677.         part_num = 1;
  678.         goto fresh_indexing;
  679.     }
  680.  
  681.     /* Find out existing index of words and partitions/filenumbers */
  682.     if ((indextype = get_index_type(s)) < 0) {
  683. #if    0
  684.         fprintf(stderr, "Fresh indexing recommended: -a and -f are not supported with -b as yet\n");
  685.         exit(1);
  686.         /* we support it now */
  687. #endif
  688.     }
  689.     file_num = part_num = 0;
  690.     sprintf(s, "%s/%s", INDEX_DIR, NAME_LIST);
  691.     file_num = get_array_of_lines(s, name_list, MaxNum24bPartition, 1);
  692.     initialize_disable_list(file_num);
  693.     initialize_data_structures(file_num);
  694.  
  695.     if (!indextype) {
  696.         sprintf(s, "%s/%s", INDEX_DIR, P_TABLE);
  697.         part_num = get_table(s, p_table, MAX_PARTITION, 1) - 1;    /* part_num INCLUDES last partition */
  698.     }
  699.     else merge_splits();
  700.  
  701.     /* Check for errors, Set OneFilePerBlock */
  702.     if ( (file_num <= 0) || (!indextype && (part_num <= 0)) ) {
  703.         if (AddToIndex || DeleteFromIndex) {
  704.         fprintf(stderr, "Cannot find previous glimpseindex files! Fresh indexing recommended\n");
  705.         return usage(0);
  706.         }
  707.         file_num = 0;
  708.         file_id = 0;
  709.         part_num = 1;
  710.         my_free(disable_list);
  711.         disable_list = NULL;
  712.         goto fresh_indexing;
  713.     }
  714.     if (OneFilePerBlock && !indextype) {
  715.         fprintf(stderr, "Warning: ignoring option -o: using format of existing index\n");
  716.     }
  717.     OneFilePerBlock = abs(indextype);
  718.     if (indextype < 0) ByteLevelIndex = ON;
  719.  
  720.     /* Used in FastIndex for all existing files, used in AddToIndex/DeleteFromIndex if we are trying to add/remove an existing file */
  721.     build_filename_hashtable(name_list, file_num);
  722.  
  723. #if    0
  724.     /* Test if these are inverses of each other */
  725.     save_data_structures();
  726.     merge_splits();
  727. #endif    /*0*/
  728.  
  729.     /*
  730.      * FastIndex: set disable-flag for unchanged files: remove AND
  731.      * disable non-existent files. Let hole remain in file-names/partitions.
  732.      */
  733.     if (FastIndex) {
  734.         for (i=0; i<file_num; i++)
  735.         if (-1 == stat(LIST_GET(name_list, i), &stbuf)) {
  736.             remove_filename(i, -1);
  737.         }
  738.         else if (((stbuf.st_mode & S_IFMT) == S_IFREG) && (stbuf.st_ctime <= istbuf.st_ctime)) {
  739.             /* This is just used as a cache since exclude/include processing is not done here: see dir.c */
  740.             disable_list[block2index(i)] |= mask_int[i % (8*sizeof(int))];
  741.         }
  742.         else {
  743.             /* Can't do it for directories since files in it can be modified w/o date reflected in the directory. Same for symlinks. */
  744.             LIST_ADD(size_list, i, stbuf.st_size, int);
  745.             disable_list[block2index(i)] &= ~(mask_int[i % (8*sizeof(int))]);
  746.         }
  747.     }
  748.     /*
  749.      * AddToIndex without FastIndex: disable all existing files, remove those that don't exist now.
  750.      * Out of old ones, only ADDED FILES are re-enabled: dir.c
  751.      */
  752.     else if (AddToIndex) {
  753.         for (i=0; i<file_num; i++) {
  754.         if (-1 == stat(LIST_GET(name_list, i), &stbuf)) {
  755.             remove_filename(i, -1);
  756.         }
  757.         else {
  758.             LIST_ADD(size_list, i, stbuf.st_size, int);    /* ONLY for proper statistics in save_data_structures() */
  759.             disable_list[block2index(i)] |= mask_int[i % (8*sizeof(int))];
  760.         }
  761.         }
  762.     }
  763.     /* else: DeleteFromIndex without FastIndex: don't touch other files */
  764.  
  765.     old_file_num = file_num;
  766.     destroy_data_structures();
  767.  
  768.     /* Put old/new files into partitions/filenumbers */
  769.     if (-1 == oldpartition(argc, argv)) {
  770.         for(i=0;i<file_num;i++) {
  771. #if    BG_DEBUG
  772.         memory_usage -= (strlen(LIST_GET(name_list, i)) + 2);
  773. #endif    /*BG_DEBUG*/
  774.         if (LIST_GET(name_list, i) != NULL) {
  775.             my_free(LIST_GET(name_list, i), 0);
  776.             LIST_SUREGET(name_list, i) = NULL;
  777.         }
  778.         }
  779.         file_num = 0;
  780.         file_id = 0;
  781.         for (i=0;i<part_num; i++) {
  782.         p_table[i] = 0;
  783.         }
  784.         part_num = 1;
  785.         my_free(disable_list);
  786.         disable_list = NULL;
  787.         goto fresh_indexing;
  788.     }
  789.  
  790.     /* Reindex all the files but use the file-names obtained with oldpartition() */
  791.     if (cross_boundary(OneFilePerBlock, file_num)) {
  792.         my_free(disable_list);
  793.         disable_list = NULL;
  794.     }
  795.  
  796.     initialize_data_structures(file_num);
  797.     if (!DeleteFromIndex || FastIndex) build_index();
  798.     if ((deletedlist = get_removed_indices()) == NULL) new_file_num = file_num;
  799.     else if (PurgeIndex) new_file_num = purge_index();
  800.  
  801. #if    BG_DEBUG
  802.     fprintf(LOGFILE, "Built indices in %s/%s\n", INDEX_DIR, INDEX_FILE);
  803. #endif    /*BG_DEBUG*/
  804.     goto docleanup;
  805.     }
  806.  
  807. fresh_indexing:
  808.     /* remove it to create space since it can be large: don't need for fresh indexing */
  809.     sprintf(s, "%s/%s", INDEX_DIR, P_TABLE);
  810.     unlink(s);
  811.     /* These should be zeroed since they can confuse fsize and fsize_directory() */
  812.     AddToIndex = 0;
  813.     FastIndex = 0;
  814. #if    BG_DEBUG
  815.     fprintf(LOGFILE, "Commencing fresh indexing\n");
  816. #endif    /*BG_DEBUG*/
  817.     partition(argc, argv);
  818.     destroy_filename_hashtable();
  819.     initialize_data_structures(file_num);
  820.     old_file_num = file_num;
  821.     build_index();
  822. #if    BG_DEBUG
  823.     fprintf(LOGFILE, "\nBuilt indices in %s/%s\n", INDEX_DIR, INDEX_FILE);
  824. #endif    /*BG_DEBUG*/
  825.  
  826. docleanup:
  827.     cleanup();
  828.     save_data_structures();
  829.     destroy_filename_hashtable();
  830. #if    BG_DEBUG
  831.     fflush(LOGFILE);
  832.     fclose(LOGFILE);
  833. #endif    /*BG_DEBUG*/
  834.     fflush(MESSAGEFILE);
  835.     fclose(MESSAGEFILE);
  836.     fflush(STATFILE);
  837.     fclose(STATFILE);
  838.     if (AddedMaxWordsMessage) printf("\nSome files contributed > %d words to the index: check %s\n", MAXWORDSPERFILE, DEF_MESSAGE_FILE);
  839.     if (AddedMixedWordsMessage) printf("Some files had numerals in > %d%% of the indexed words: check %s\n", NUMERICWORDPERCENT, DEF_MESSAGE_FILE);
  840.  
  841.     printf("\nIndex-directory: \"%s\"\nGlimpse-files created here:\n", INDEX_DIR);
  842.     chdir(INDEX_DIR);
  843.     sprintf(s, "exec %s -lg .glimpse_* > /tmp/%d\n", SYSTEM_LS, pid);
  844.     system(s);
  845.     sprintf(s, "/tmp/%d", pid);
  846.     if ((tmpfp = fopen(s, "r")) != NULL) {
  847.     memset(tmpbuf, '\0', 1024);
  848.     while(fgets(tmpbuf, 1024, tmpfp) != NULL) fputs(tmpbuf, stdout);
  849.     fflush(tmpfp);
  850.     fclose(tmpfp);
  851.     unlink(s);
  852.     }
  853.     else fprintf(stderr, "cannot open %s to `cat': check %s for .glimpse - files\n", s, INDEX_DIR);
  854. #endif    /*BUILDCAST*/
  855.  
  856.     return 0;
  857. }
  858.  
  859. cleanup()
  860. {
  861.     char s[MAX_LINE_LEN];
  862.  
  863.     sprintf(s, "%s/%s", INDEX_DIR, I1);
  864.     unlink(s);
  865.     sprintf(s, "%s/%s", INDEX_DIR, I2);
  866.     unlink(s);
  867.     sprintf(s, "%s/%s", INDEX_DIR, I3);
  868.     unlink(s);
  869.     sprintf(s, "%s/%s", INDEX_DIR, O1);
  870.     unlink(s);
  871.     sprintf(s, "%s/%s", INDEX_DIR, O2);
  872.     unlink(s);
  873.     sprintf(s, "%s/%s", INDEX_DIR, O3);
  874.     unlink(s);
  875.     sprintf(s, "%s/.glimpse_apply.%d", INDEX_DIR, getpid());
  876.     unlink(s);
  877. }
  878.  
  879. #if    !BUILDCAST
  880. usage(flag)
  881. int    flag;
  882. {
  883.     if (flag) fprintf(stderr, "\nThis is glimpseindex version %s, %s.\n\n", GLIMPSE_VERSION, GLIMPSE_DATE);
  884.     fprintf(stderr, "usage: %s [-help] [-a] [-d] [-f] [-i] [-n [#]] [-o] [-s] [-w #] [-B] [-F] [-H dir] [-I] [-M] [-S lim] [-T] [-V] dirs/files\n", IProgname);
  885.         fprintf(stderr, "summary of frequently used options\n(for a more detailed listing see 'man glimpse'):\n");
  886.     fprintf(stderr, "-help: outputs this menu\n");
  887.         fprintf(stderr, "-a: add given files/dirs to an existing index\n");
  888.         fprintf(stderr, "-d: delete given files/dirs from an existing index\n");
  889.     fprintf(stderr, "-b: build a (large) byte level index to speed up search\n");
  890.         fprintf(stderr, "-f: use modification dates to do fast indexing\n");
  891.         fprintf(stderr, "-n #: index numbers; warn if file adds > #%% numeric words: default is 50\n");
  892.         fprintf(stderr, "-o: optimize for speed by building a larger index\n");
  893.     /* fprintf(stderr, "-s: build the index for structured queries (a1=v1 &/| a2=v2...)\n"); this should not be advertised */
  894.         fprintf(stderr, "-w #: warn if a file adds > # words to the index\n");
  895.     fprintf(stderr, "-F: expect filenames on stdin (useful for pipelining)\n");
  896.         fprintf(stderr, "-H 'dir': .glimpse-files should be in directory 'dir': default is '~'\n");
  897.     fprintf(stderr, "-T: build .glimpse_turbo for very fast search with -i -w in glimpse\n");
  898.     fprintf(stderr, "\n");
  899.     fprintf(stderr, "For questions about glimpse, please contact `%s'\n", GLIMPSE_EMAIL);
  900.     exit(1);
  901. }
  902. #else    /*!BUILDCAST*/
  903. usage(flag)
  904. int    flag;
  905. {
  906.     if (flag) fprintf(stderr, "\nThis is buildcast version %s, %s.\n\n", GLIMPSE_VERSION, GLIMPSE_DATE);
  907.     fprintf(stderr, "usage: %s [-help] [-t] [-i] [-l] [-n [#]] [-w #] [-C] [-E] [-F] [-H dir] [-V] dirs/files\n", IProgname);
  908.         fprintf(stderr, "summary of frequently used options\n(for a more detailed listing see 'man cast'):\n");
  909.     fprintf(stderr, "-help: output this menu\n");
  910.         fprintf(stderr, "-n #: index numbers; warn if file adds > #%% numeric words: default is 50\n");
  911.         fprintf(stderr, "-w #: warn if a file adds > # words to the index\n");
  912.     fprintf(stderr, "-C: compress files with the new dictionary after building it\n");
  913.     fprintf(stderr, "-E: build cast dictionary using existing compressed files only\n");
  914.     fprintf(stderr, "-F: expect filenames on stdin (useful for pipelining)\n");
  915.         fprintf(stderr, "-H 'dir': .glimpse-files should be in directory 'dir': default is '~'\n");
  916.     fprintf(stderr, "\n");
  917.     fprintf(stderr, "For questions about glimpse, please contact `%s'\n", GLIMPSE_EMAIL);
  918.     exit(1);
  919. }
  920. #endif    /*!BUILDCAST*/
  921.